﻿using System.Text;

namespace DHTools
{
    public static class XMD
    {
        /// <summary>
        /// Loads animation data from a byte array.
        /// </summary>
        public static XAnimation[] LoadAnimations(byte[] data)
        {
            using (var ms = new MemoryStream(data))
            using (var reader = new BinaryReader(ms))
            {
                byte[] header = reader.ReadBytes(18);
                int boneCount = reader.ReadInt32();
                int unknownValue = reader.ReadInt32();
                uint animationCount = FileDataHelper.ReadVarInt(reader);
                XAnimation[] animations = new XAnimation[animationCount];

                for (var i = 0; i < animationCount; i++)
                {
                    animations[i] = LoadAnimation(reader);
                }

                return animations;
            }
        }

        private static XAnimation LoadAnimation(BinaryReader reader)
        {
            var animation = new XAnimation
            {
                name = ReadString(reader),
                duration = reader.ReadSingle(),
                nKeys = FileDataHelper.ReadVarInt(reader)
            };

            animation.keys = new XAnimationKey[animation.nKeys];

            for (var i = 0; i < animation.nKeys; i++)
            {
                animation.keys[i] = LoadAnimationKey(reader);
            }

            return animation;
        }

        private static XAnimationKey LoadAnimationKey(BinaryReader reader)
        {
            var key = new XAnimationKey
            {
                time = reader.ReadSingle(),
                scaleTransforms = new XScaleTransform[FileDataHelper.ReadVarInt(reader)],
                transforms = new XTransform[FileDataHelper.ReadVarInt(reader)]
            };

            for (var i = 0; i < key.scaleTransforms.Length; i++)
            {
                key.scaleTransforms[i] = LoadScaleTransform(reader);
            }

            for (var i = 0; i < key.transforms.Length; i++)
            {
                key.transforms[i] = LoadTransform(reader);
            }

            return key;
        }

        private static XScaleTransform LoadScaleTransform(BinaryReader reader)
        {
            var scaleTransform = new XScaleTransform
            {
                rotation = new XQuaternion(),
                scale = new XVector3(),
                position = new XVector3()
            };

            for (var i = 0; i < 4; i++) scaleTransform.rotation[i] = reader.ReadSingle();
            for (var i = 0; i < 3; i++) scaleTransform.scale[i] = reader.ReadSingle();
            for (var i = 0; i < 3; i++) scaleTransform.position[i] = reader.ReadSingle();

            return scaleTransform;
        }

        private static XTransform LoadTransform(BinaryReader reader)
        {
            var transform = new XTransform
            {
                rotation = new XQuaternion(),
                position = new XVector3()
            };

            for (var i = 0; i < 4; i++) transform.rotation[i] = reader.ReadSingle();
            for (var i = 0; i < 3; i++) transform.position[i] = reader.ReadSingle();

            return transform;
        }

        private static string ReadString(BinaryReader reader)
        {
            var length = (int)FileDataHelper.ReadVarInt(reader);
            var data = reader.ReadBytes(length);
            return Encoding.Unicode.GetString(data, 0, data.Length);
        }
    }
}